/**
 * 
 */
package com.kingpigeon.iotsvrdemo;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.Attribute;

/**
 * @author xuhw
 *
 */
public class DeviceSvrHandler extends ChannelInboundHandlerAdapter {
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception
	{
		System.out.println("handlerRemoved："+ctx.channel().remoteAddress());
		Attribute<String> attrMac = ctx.attr(KingPigeonUtils.attributeKeyMAC); 
    	
		if(attrMac.get() == null)
		{
			System.out.println("offline ,disconnect directly");
		}
		else
		{
			System.out.println("offline Mac:"+attrMac.get());
			if(null == KingPigeonUtils.deviceChannels.get(attrMac.get()))
			{

				System.out.println("offline mac not found in deviceChannels");
			}
			else
			{//防止设备断线重连，旧的连接通道关闭信号影响新连接
				System.out.println("offline mac found in deviceChannels:"+KingPigeonUtils.deviceChannels.get(attrMac.get()));
				if(KingPigeonUtils.deviceChannels.get(attrMac.get()).equals(ctx))
				{
					System.out.println("offline chl found in deviceChannels,remove it:"+KingPigeonUtils.deviceChannels.get(attrMac.get()));
					KingPigeonUtils.deviceChannels.remove(attrMac.get());
					
				}
				else
				{
					System.out.println("offline chl not found in deviceChannels,do nothing:"+KingPigeonUtils.deviceChannels.get(attrMac.get()));
					
				}
			}
		}
	}
	public void handlerAdded(ChannelHandlerContext ctx) throws Exception
	{
		System.out.println("handlerAdded："+ctx.channel().remoteAddress());
		String sRandom8 = KingPigeonUtils.GenRandomNumber(8);
		byte [] bMsgBody = new byte[8];
    	System.arraycopy(KingPigeonUtils.bytesFromHexString(sRandom8), 							0, bMsgBody, 0, 4);
    	System.arraycopy(KingPigeonUtils.intToBytesLe((int)(System.currentTimeMillis() / 1000)),0, bMsgBody, 4, 4);
		System.out.println("sRandom8：["+sRandom8+"]utctime(litte-endian hexstring)：["+ByteBufUtil.hexDump(KingPigeonUtils.intToBytesLe((int)(System.currentTimeMillis() / 1000)))+"]0x80bMsgBody：["+ByteBufUtil.hexDump(bMsgBody)+"]");
		ctx.writeAndFlush(Unpooled.copiedBuffer(KingPigeonUtils.bMsgPackage("80",bMsgBody,8)));
	}
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        ByteBuf buf = (ByteBuf) msg;
        if(buf.readableBytes() <=0)
        {//System.out.println("too short msg");
        	return;
        }
        int iDataLength = buf.readableBytes();
        System.out.println("RawDataReceived["+iDataLength+"]["+ByteBufUtil.hexDump(buf)+"]");
        byte[] rawdata = new byte[iDataLength];
        buf.readBytes(rawdata);
        //the delimiter 0xA5 has been stripped by the netty DelimiterBasedFrameDecoder, we added it here for convenience's sake.
        byte[] rawdataWithDelimiter = new byte[iDataLength+2];
        System.arraycopy(rawdata, 0, rawdataWithDelimiter, 1, iDataLength);
        rawdataWithDelimiter[0] = KingPigeonUtils.Delimiter;
        rawdataWithDelimiter[iDataLength+1] = KingPigeonUtils.Delimiter;
        /*转义*/
        byte[] data = KingPigeonUtils.EscapeCharaterConvertRecv(rawdataWithDelimiter);
        System.out.println("DataAfterConverted["+data.length+"]["+ByteBufUtil.hexDump(data)+"]");
        /*xuhw : save the ChannelHandlerContext to the map*/
        /*此次可根据MAC更新设备在线状态，通讯时间戳（以便心跳程序 判断其是否超时未响应）*/
        String sMac = KingPigeonUtils.bytesToAscii(data,8,15);
        KingPigeonUtils.deviceChannels.put(sMac, ctx);
    	System.out.println("deviceChannels:"+KingPigeonUtils.deviceChannels.toString());
    	Attribute<String> attrMac = ctx.attr(KingPigeonUtils.attributeKeyMAC); 
    	if(attrMac.get() == null)
    	{ 		
    		attrMac.set(sMac);
			System.out.println("online first time, set Mac attr:"+attrMac.get());   
    	}
    	else
    	{
			System.out.println("online Mac not null:"+attrMac.get());     		
    		attrMac.set(sMac);  
    	}
    	/**在该MAP中，可通过十六进制MAC码找到对应的通道， 服务器便可主动下发下行报文给相应RTU设备
         * In the MAP, the corresponding channel can be found according to the hexadecimal MAC code, and the server can actively send the downlink message to the RTU device.
        KingPigeonUtils.deviceChannels.get("863977033874947").writeAndFlush(Unpooled.copiedBuffer("ACK".getBytes()));
         */
    	byte bCMD = data[3];
        if( bCMD==KingPigeonUtils.RTUCMD70){
        	System.out.println("RTUCMD70");
        	new RTUCMD70UP(ctx,data).RTUCMD70UPHandler();;
        }
        else if( bCMD==KingPigeonUtils.RTUCMD71){
        	System.out.println("RTUCMD71");
        	new RTUCMD71UP(ctx,data).RTUCMD71UPHandler();;
        }
        else if( bCMD==KingPigeonUtils.RTUCMD72){
        	System.out.println("RTUCMD72");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD73){
        	System.out.println("RTUCMD73");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD80){
        	System.out.println("RTUCMD80");
        	new RTUCMD80UP(ctx,data).RTUCMD80UPHandler();;
        }
        else if( bCMD==KingPigeonUtils.RTUCMD81){
        	System.out.println("RTUCMD81");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD82){
        	System.out.println("RTUCMD82");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD83){
        	System.out.println("RTUCMD83");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD84){
        	System.out.println("RTUCMD84");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD85){
        	System.out.println("RTUCMD85");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD86){
        	System.out.println("RTUCMD86");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD87){
        	System.out.println("RTUCMD87");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD88){
        	System.out.println("RTUCMD88");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD89){
        	System.out.println("RTUCMD89");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD8A){
        	System.out.println("RTUCMD8A");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD8B){
        	System.out.println("RTUCMD8B");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD8C){
        	System.out.println("RTUCMD8C");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD8D){
        	System.out.println("RTUCMD8D");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD8E){
        	System.out.println("RTUCMD8E");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD94){
        	System.out.println("RTUCMD94");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD97){
        	System.out.println("RTUCMD97");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD99){
        	System.out.println("RTUCMD99");
        }
        else if( bCMD==KingPigeonUtils.RTUCMDA0){
        	System.out.println("RTUCMDA0");
        }
        else if( bCMD==KingPigeonUtils.RTUCMDA1){
        	System.out.println("RTUCMDA1");
        }
        else if( bCMD==KingPigeonUtils.RTUCMDA2){
        	System.out.println("RTUCMDA2");
        }
        else if( bCMD==KingPigeonUtils.RTUCMDA3){
        	System.out.println("RTUCMDA3");
        }
        else if( bCMD==KingPigeonUtils.RTUCMD8F){
        	System.out.println("RTUCMD8F");
        }
        else if( bCMD==KingPigeonUtils.RTUCMDB0){
        	System.out.println("RTUCMDB0");
        }
        else if( bCMD==KingPigeonUtils.RTUCMDB1){
        	System.out.println("RTUCMDB1");
        }
        else if( bCMD==KingPigeonUtils.RTUCMDB2){
        	System.out.println("RTUCMDB2");
        }
        else if( bCMD==KingPigeonUtils.RTUCMDB3){
        	System.out.println("RTUCMDB3");
        }
        else if( bCMD==KingPigeonUtils.RTUCMDB4){
        	System.out.println("RTUCMDB4");
        }
    }
	/**
	 * 
	 */

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
